/// @file test_modular_auth/main.cpp
/// @brief Test for the modular authentication system
/// 
/// This file tests the modular authentication system with UiAo, AuthAo, and DbAo.

#include <unity.h>
#include "ui_ao.h"
#include "auth_ao.h"
#include "db_ao.h"
#include "auth_events.h"
#include "qpcpp.hpp"
#include <thread>
#include <chrono>
#include <spdlog/spdlog.h>

// Test result flags
static bool login_success_event = false;
static bool login_failure_event = false;
static bool register_success_event = false;
static bool register_failure_event = false;

// Event handlers for UI AO responses
static void onLoginSuccess(QP::QEvt const* e) {
    login_success_event = true;
    spdlog::info("Test: Login success event received");
}

static void onLoginFailure(QP::QEvt const* e) {
    login_failure_event = true;
    spdlog::info("Test: Login failure event received");
}

static void onRegisterSuccess(QP::QEvt const* e) {
    register_success_event = true;
    spdlog::info("Test: Register success event received");
}

static void onRegisterFailure(QP::QEvt const* e) {
    register_failure_event = true;
    spdlog::info("Test: Register failure event received");
}

void setUp(void) {
    // Initialize QP framework for this test
    QP::QF::init();
    
    // Reset test result flags
    login_success_event = false;
    login_failure_event = false;
    register_success_event = false;
    register_failure_event = false;
    
    // Subscribe to UI AO response events
    the_AO_Ui->subscribe(LOGIN_RESPONSE_SUCCESS_SIG);
    the_AO_Ui->subscribe(LOGIN_RESPONSE_FAILURE_SIG);
    the_AO_Ui->subscribe(REGISTER_RESPONSE_SUCCESS_SIG);
    the_AO_Ui->subscribe(REGISTER_RESPONSE_FAILURE_SIG);
    
    spdlog::info("Test setup completed");
}

void tearDown(void) {
    // Clean up
    spdlog::info("Test teardown completed");
}

// Test successful user registration
void test_auth_register_success(void) {
    spdlog::info("Starting test_auth_register_success");
    
    // Send register request through UI AO
    RegisterRequestEvt* registerEvt = Q_NEW(RegisterRequestEvt, REGISTER_REQUEST_SIG);
    registerEvt->username = "testuser";
    registerEvt->password = "testpass";
    the_AO_Ui->POST(registerEvt, nullptr);
    
    // Wait a bit for the async operations to complete
    std::this_thread::sleep_for(std::chrono::milliseconds(200));
    
    // Check if register success event was received
    TEST_ASSERT_TRUE(register_success_event);
    TEST_ASSERT_FALSE(register_failure_event);
}

// Test user login after registration
void test_auth_login_success(void) {
    spdlog::info("Starting test_auth_login_success");
    
    // First, register a user
    RegisterRequestEvt* registerEvt = Q_NEW(RegisterRequestEvt, REGISTER_REQUEST_SIG);
    registerEvt->username = "loginuser";
    registerEvt->password = "loginpass";
    the_AO_Ui->POST(registerEvt, nullptr);
    
    // Wait for registration to complete
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    
    // Then, login with the same credentials
    LoginRequestEvt* loginEvt = Q_NEW(LoginRequestEvt, LOGIN_REQUEST_SIG);
    loginEvt->username = "loginuser";
    loginEvt->password = "loginpass";
    the_AO_Ui->POST(loginEvt, nullptr);
    
    // Wait a bit for the async operations to complete
    std::this_thread::sleep_for(std::chrono::milliseconds(200));
    
    // Check if login success event was received
    TEST_ASSERT_TRUE(login_success_event);
    TEST_ASSERT_FALSE(login_failure_event);
}